home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Just Call Me Internet
/
Just Call Me Internet.iso
/
prog
/
atari
/
c
/
nos042_s
/
dirutil.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-16
|
12KB
|
427 lines
/*----------------------------------------------------------------------------
dirutil.c - ATARI ST directory reading routines
ST NOS Version by David Nash, dnash@chaos.demon.co.uk
21.08.94 DFN - Remove blank padding in short, single column list.
----------------------------------------------------------------------------*/
#include <stdio.h>
#include <ctype.h>
#include <osbind.h>
#include <dos.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include "global.h"
#include "commands.h"
#undef time /* remove macro from global.h */
static struct FILEINFO info; /* file information = dta */
static void format_dir(char *, struct stat);
static void format_fname(char *, char *, char);
static void diskfree(FILE *, int, int);
static void format_dirent(char *line, char *name, struct stat *st_buf, int full);
int getdir(char *, int full, FILE *);
void path_u2d(char *);
#define NULLSORT (struct dirsort *)0
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (!0)
#endif
#define DIR_NAMES 256
#define PATH_LEN 256
#define FILE_L 13
/*---------------------------------------------------------------------------
dir - Create a directory listing in a temp file and return the
resulting file descriptor. If full == 1, give a full listing;
else return just a list of names.
---------------------------------------------------------------------------*/
FILE *dir(char *path, int full) {
FILE *fp;
if ((fp = tmpfile()) != NULLFILE) {
getdir(path, full, fp);
rewind(fp);
}
return fp;
}
/*---------------------------------------------------------------------------
filedir - wildcard filename lookup
---------------------------------------------------------------------------*/
void filedir(char *name, int times, char *ret_str) {
char *cp, *cp1;
Fsetdta(&info); /* Set disk transfer address */
path_u2d(name); /* convert path seperators */
/* Find matching file */
if (times == 0 ? Fsfirst(name, 0x11) : Fsnext()) /* include r/o and dir */
info.name[0] = '\0'; /* file name not found */
/* Copy result to output, forcing to lower case */
for(cp = ret_str, cp1 = info.name; cp1 < &info.name[13] && *cp1 != '\0'; )
*cp++ = (char)tolower(*cp1++);
*cp = '\0';
}
/*---------------------------------------------------------------------------
getdir - do a directory list to the stream
full = 0 -> short form, list of valid file names seperated by '\n'
1 -> long form, filenames and statistics
-1 -> multi-column short
---------------------------------------------------------------------------*/
int getdir(char *path, int full, FILE *file) {
int indx = 0, i = 0;
int no_files = 0;
int count = 0;
int drive_n;
int flag = 0;
int cols = 1;
char drive_c;
char *path_p, *path_q; /* pointer into path string */
char line_buf[50]; /* for long dirlist */
char fq_path[128]; /* fully quilified path */
char fq_name[128]; /* fully qualified name */
char **name_p; /* pointers to file names */
char *names; /* array of file names */
char *name_ptr; /* pointer into names array */
struct stat st_buf; /* buffer for stat results */
struct stat *st_buf_p = 0; /* pointer to stat buffer */
struct dirent *dp; /* directory entry pointer */
DIR *dir; /* directory stream pointer */
path_u2d(path); /* convert path seperators */
if (full > 0)
cols = 2; /* long listing format */
else if (full < 0)
cols = 5; /* multi column wide format */
else
cols = 1; /* one column short list */
/* Analyse the path components */
if (path[1] == ':') {
drive_c = path[0]; /* set drive letter */
drive_n = toupper(path[0]) - 'A' + 1; /* set drive number, a=1 */
path_p = path + 2; /* point past drive letter */
}
else {
drive_n = Dgetdrv() + 1; /* get default drive, a=1 */
drive_c = drive_n + 'A' - 1; /* default drive letter */
path_p = path; /* point to full path */
}
if (*path_p == '.')
path++; /* remove . (current dir) */
if (*path_p == '.')
path_p++; /* remove .. (previous dir) */
if (path[0] == '\\') /* process absolute path */
sprintf(fq_path, "%c:%s\0", drive_c, path_p);
else if (path[1] == ':' && path[2] == '\\')
sprintf(fq_path, "%s\0", path);
else { /* process relative path */
Dgetpath(fq_name, drive_n); /* get current directory */
sprintf(fq_path, "%c:%s\\%s\0", drive_c, fq_name, path_p);
}
if (fq_path[strlen(fq_path) -1] != '\\')
strcat(fq_path, "\\"); /* must end in \ */
/* Strip out duplicate '\' characters */
for (path_p = path_q = fq_path; *path_p; path_p++) {
if (flag) /* alraedy got a slash */
if (*path_p == '\\')
continue; /* we dont't want another */
else
flag = 0; /* normal char, clear flag */
else /* last char was normal */
if (*path_p == '\\')
flag = 1; /* got a slash, set flag */
*path_q++ = *path_p; /* copy the char */
}
*path_q = '\0'; /* force end of string */
/* Process the dirctory */
if ((dir = opendir(fq_path)) == NULL) { /* open the directory */
fprintf(file, "Path %s not found \n", path);
return -1; /* error, directory not found */
}
while (readdir(dir)) /* count number of entries */
count++;
count += 10; /* add fudge factor */
rewinddir(dir); /* reset directory pointer */
if ((names = (char *)calloc(count * FILE_L, sizeof(char))) == NULL) {
closedir(dir);
tprintf("getdir: calloc failed for names \n");
return -1;
}
if ((name_p = (char **)calloc(count, sizeof(char *))) == NULL) {
free(names);
closedir(dir);
tprintf("getdir: calloc failed for name_p \n");
return -1;
}
name_ptr = names; /* initilise the pointer */
while (dp = readdir(dir)) {
if (dp->d_name[0] == '.')
continue; /* ignore 'hidden' files */
strncpy(name_ptr, dp->d_name, dp->d_reclen);
name_p[indx] = name_ptr; /* setup pointer */
name_ptr += dp->d_reclen + 1;
indx++;
} /* END of while loop */
if (closedir(dir) != 0) /* close the directory */
tprintf("getdir: closedir failed %s \n", strerror(errno));
no_files = indx; /* save number of files */
tqsort(name_p, no_files); /* sort the pointers */
/* Format and write the output */
for (indx = 0; indx < no_files; indx++) {
if (full > 0) {
st_buf_p = &st_buf; /* may have been reset */
sprintf(fq_name, "%s%s\0", fq_path, name_p[indx]);
if (stat(fq_name, st_buf_p) == -1) {
st_buf_p = 0;
}
}
format_dirent(line_buf, name_p[indx], st_buf_p, full);
fprintf(file, "%s%s", line_buf, (++i % cols) ? " " : "\n");
}
if (i % cols)
fprintf(file, "\n");
if (full > 0)
diskfree(file, drive_n, no_files);
free(names); /* free the file name array */
free(name_p); /* free the pointer array */
return 0; /* return OK */
}
/*---------------------------------------------------------------------------
format_dirent - format a directory entry
---------------------------------------------------------------------------*/
static void format_dirent( char *line,
char *name,
struct stat *st_buf,
int full
)
{
char *p, *q;
char size[12]; /* file size */
char time[15]; /* file modification time */
char fname[14]; /* formatted file name */
*line = '\0'; /* clear the output buffer */
for (p = name, q = fname; *p && *p != ' '; p++, q++)
*q = tolower(*p);
*q = '\0'; /* terminate the string */
if (full == 0) {
strcpy(line, fname);
return; /* short, NL terminated list */
}
if (full < 0) { /* short multi line format */
sprintf(line, "%-13s\0", fname);
return;
}
if (S_ISDIR(st_buf->st_mode)) {
*q++ = '/';
sprintf(size, " "); /* no size for dir */
}
else
sprintf(size, "%ld", st_buf->st_size);
*q = '\0'; /* set EOS for file name */
strftime(time, sizeof(time), "%H:%M %d.%m.%y", localtime(&st_buf->st_mtime));
sprintf(line, "%8s %14s %-13s", size, time, fname);
}
/*---------------------------------------------------------------------------
diskfree - return stats
---------------------------------------------------------------------------*/
void diskfree (FILE *file, int drv, int nfiles)
{
unsigned long free_bytes = 0;
unsigned long total_bytes = 0;
struct DISKINFO disk_info;
char s_free[11];
char s_total[11];
fflush(stdout); /* function takes a short while... */
if (Dfree((void *)&disk_info, (short)drv) == 0) {
free_bytes = disk_info.bps * disk_info.spc;
total_bytes = free_bytes * disk_info.cpd;
free_bytes *= disk_info.free;
}
sprintf(s_free, "%ld", free_bytes);
sprintf(s_total,"%ld", total_bytes);
if (nfiles)
fprintf(file, "\n%d", nfiles);
else
fprintf(file, "No");
fprintf(file, " file%s. %s bytes free. Disk size %s bytes.\r\n",
(nfiles == 1 ? "" : "s"), s_free, s_total);
}
/*---------------------------------------------------------------------------
Change working directory
---------------------------------------------------------------------------*/
docd(int argc, char *argv[], void *p)
{
char dirname[128];
if(argc > 1) {
path_u2d(argv[1]); /* convert path seperators */
if(chdir(argv[1])){
printf("Can't change directory\n");
return 1;
}
}
if (Dgetpath(dirname,0) == 0){
printf("%c:%s%s\n",(char) Dgetdrv()+'A',
(*dirname ? "" : "\\"),dirname);
}
return 0;
}
/*---------------------------------------------------------------------------
dodir - List directory to console. [-]w option selects "wide" format
---------------------------------------------------------------------------*/
int __stdargs dodir(int argc, char *argv[], void *p) {
char path[PATH_LEN];
int full = 1;
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'w') {
full = -1;
argv++;
argc--;
}
if (argc >= 2) {
strncpy(path, argv[1], PATH_LEN);
} else {
strcpy(path, ".");
}
getdir(path, full, stdout);
return 0;
}
/*---------------------------------------------------------------------------
domkd - Create directory
---------------------------------------------------------------------------*/
int domkd(int argc, char *argv[], void *p)
{
if (mkdir(argv[1]) == -1)
tprintf("Can't make %s: %s\n", argv[1], strerror(errno));
return 0;
}
/*---------------------------------------------------------------------------
dormd - Remove directory
---------------------------------------------------------------------------*/
int dormd(int argc, char *argv[], void *p)
{
if (rmdir(argv[1]) == -1)
tprintf("Can't remove %s: %s\n", argv[1], strerror(errno));
return 0;
}
/*---------------------------------------------------------------------------
path_u2d - convert unix style path seperators to dos style seperators
---------------------------------------------------------------------------*/
void path_u2d(char *name)
{
char *p;
for (p = name; *p; p++)
if (*p == '/')
*p = '\\';
return;
}